import { Editor } from '@three/Editor';
import type { Tree, TreeDataNode, TreeProps } from 'antd';
import type { FC, Key, ReactElement, Ref, RefAttributes } from 'react';
import { useEffect, useRef, useState } from 'react';
import type { Object3D } from 'three/webgpu';

import { TreeComponent } from '@/components/TreeComponent';

import { generateData, getAncestorsKeys } from './util';

type RcTree = typeof Tree extends (props: RefAttributes<infer P>) => ReactElement ? P : never;

export const SceneView: FC = () => {
  const treeRef: Ref<RcTree> = useRef(null);

  const [treeData, setTreeData] = useState<TreeDataNode[]>([]);
  const [expandedKeys, setExpandedKeys] = useState<Key[]>([]);
  const [selectedKeys, setSelectedKeys] = useState<Key[]>([]);

  const onSelect: TreeProps['onSelect'] = (keys, _info) => {
    const key = keys[0];
    Editor.instance?.selectByUuid(key as string);
  };

  useEffect(() => {
    const onObjectSelected = (object: Object3D | null) => {
      if (object === null) {
        setExpandedKeys([Editor.instance?.scene.uuid as string]);
        setSelectedKeys([]);
      } else {
        setExpandedKeys([...getAncestorsKeys(object)]);
        setSelectedKeys([object.uuid]);
        treeRef.current?.scrollTo({ key: object.uuid });
      }
    };

    const onObjectAdded = (_object: Object3D) => {
      setTreeData([generateData(Editor.instance?.scene as Object3D)]);
    };

    if (Editor.instance) {
      Editor.instance.signals.objectSelected.add(onObjectSelected);
      Editor.instance.signals.objectAdded.add(onObjectAdded);
      setTreeData(() => [generateData(Editor.instance?.scene as Object3D)]);
    }
    return () => {
      Editor.instance?.signals.objectSelected.remove(onObjectSelected);
      Editor.instance?.signals.objectAdded.remove(onObjectAdded);
    };
  }, []);

  return (
    <div className="w-full h-[40%] bg-cyan-300 rounded-sm">
      <TreeComponent
        ref={treeRef}
        treeData={treeData}
        onSelect={onSelect}
        expandedKeys={expandedKeys}
        selectedKeys={selectedKeys}
        setExpandedKeys={setExpandedKeys}
        setSelectedKeys={setSelectedKeys}></TreeComponent>
    </div>
  );
};
